package com.wxsm.wechat.core.aop;

import com.wxsm.wechat.core.exception.ExceptionEnum;
import com.wxsm.wechat.core.exception.ServiceException;
import com.wxsm.wechat.service.UserService;
import com.wxsm.wechat.util.ActionUtil;
import com.wxsm.wechat.util.CommonUtil;
import com.wxsm.wechat.util.IPUtil;
import lombok.AllArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;

/**
 * Created with Yang Huan
 * Date: 2017/3/2
 * Time: 11:34
 */
@Aspect
@Component
@AllArgsConstructor
public class WebLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
    private final UserService userService;

    @Pointcut("execution(public * com.wxsm.wechat.controller.*.*(..))")
    public void webLog() {

    }

    @Before("webLog()")
    public void doBeforeRequest(JoinPoint joinPoint) throws Throwable {
        logger.info("request : {}", joinPoint.getSignature().getName());
        logger.info("request address: {}", ActionUtil.getRequest().getRequestURL().toString());
        logger.info("request method : {}", ActionUtil.getRequest().getMethod());
        logger.info("request ip : {}", IPUtil.getClientIp());
        logger.info("request args : {}", CommonUtil.argumentsToString(joinPoint.getArgs()));
        //该注解下的方法需登录
        NeedLogin needLogin = getAnnotation(joinPoint, NeedLogin.class);
        String openId = ActionUtil.getOpenId();
        if (null != needLogin && needLogin.needLogin() && (StringUtils.isEmpty(openId) || userService.countByOpenId(openId) == 0)) {
            throw new ServiceException(ExceptionEnum.NOT_LOGIN);
        }
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        logger.info("request result: " + ret);
    }

    private <T extends Annotation> T getAnnotation(JoinPoint point, Class<T> tClass) {
        return ((MethodSignature) point.getSignature()).getMethod().getAnnotation(tClass);
    }
}